﻿using System;
using System.Collections.Generic;
using System.Text;

namespace _2022Learning.StateMachine
{
    #region 模拟上下文类，记录信息
    /// <summary>
    /// 1.1 简略：状态设计模是属于行为设计模式之间的一种，
    /// 设计模式按照狭义上的用法或者是目的来分大致分为三类：
    /// 第一种为创建型设计模式，主要是关注对象的创建；
    /// 第二种为结构性设计模式，主要是关注类与类之间的交互之后形成更大的实体；
    /// 第三者为行为性设计模式，主要是关注对象与行为的分离；
    /// 
    /// 状态设计模式是一种行为设计模式， 让你能在一个对象的内部状态变化时改变其行为。
    /// 该模式将与状态相关的行为抽取到独立的状态类中，让原对象将工作委派给这些类的实例， 而不是自行进行处理。
    /// 
    /// </summary>
    class Context
    {
        private State _state = null;
        public Context(State state)
        {
            this.TransitionTo(state);
        }

        public void TransitionTo(State state)
        {
            Console.WriteLine($"Context: Transition to {state.GetType().Name}");
            this._state = state;
            // 切换状态并且 把当前类的信息传入到状态类中
            this._state.SetContext(this);
        }

        // 将行为传递给状态类处理
        public void Request1()
        {
            this._state.Handle1();
        }

        // 将行为传递给状态类处理
        public void Request2()
        {
            this._state.Handle2();
        }
    }
    #endregion

    #region 状态相关类
    /// <summary>
    /// 基础状态类。所有状态都要继承此类
    /// </summary>
    abstract class State
    {
        //A reference to the current state of the Context. 
        protected Context _context;
        public void SetContext(Context context)
        {
            this._context = context;
        }

        public abstract void Handle1();
        public abstract void Handle2();
    }

    /// <summary>
    /// 状态A
    /// </summary>
    class ConcreteStateA : State
    {
        public override void Handle1()
        {
            Console.WriteLine("ConcreateStateA handles request1");
            Console.WriteLine("ConcreateStateA wants to change the state of the context");
            this._context.TransitionTo(new ConcreteStateB());
        }

        public override void Handle2()
        {
            Console.WriteLine("ConcreteStateA handles request2");
        }
    }

    /// <summary>
    /// 状态B
    /// </summary>
    class ConcreteStateB : State
    {
        public override void Handle1()
        {
            Console.WriteLine("ConcreteStateB handles Request1.");
        }

        public override void Handle2()
        {
            Console.WriteLine("ConcreteStateB handles request2.");
            Console.WriteLine("COncreteStateB wants to change the state of the context");
            this._context.TransitionTo(new ConcreteStateA());
        }
    }
    #endregion
}
